package sire.ui;

import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import thinlet.FrameLauncher;

@SuppressWarnings("serial")
public class SireThinlet extends BindThinlet {

    public enum FormType {

        MDI, DIALOG
    }
    private SireThinlet parentThinlet = null;
    private Object mdi = null;
    private Dialog dialog = null;
    private WindowListener listener;
    private FormType type;

    public SireThinlet(String xml, SireThinlet parent, FormType type)
            throws Exception {
        parentThinlet = parent;
        try {
            if (type == FormType.MDI) {
                mdi = parentThinlet.parse(xml, this);
            } else if (type == FormType.DIALOG) {
                dialog = createDialog(parent);

                dialog.add(this, BorderLayout.CENTER);
                dialog.addWindowListener(listener = new WindowAdapter() {

                    public void windowClosing(WindowEvent we) {
                        try {
                            closeDialog();
                        } catch (Exception e) {
                            handleException(e);
                        }
                    }
                });

                dialog.setResizable(true);

                add(parse(xml), this);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.type = type;
    }

    public SireThinlet(String xml) throws IOException {
        add(parse(xml));
    }

    public SireThinlet getParentThinlet() {
        return parentThinlet;
    }

    public Object getMdi() {
        return mdi;
    }

    public void setModal(boolean modal) {
        if (type == FormType.MDI) {
            this.setBoolean(mdi, "modal", modal);
        }
    }

    public void closeDialog() throws IllegalAccessException {
        if (type == FormType.MDI) {
            parentThinlet.remove(mdi);
        } else if (type == FormType.DIALOG) {
            dialog.dispose();

            dialog.remove(this);
            dialog.getParent().remove(dialog);

            if (listener != null) {
                dialog.removeWindowListener(listener);
                listener = null;
            }

            releaseThinletThread();
        } else {
            System.exit(0);
        }
    }

    public void populate(Object bean) throws IllegalAccessException,
            InvocationTargetException, NoSuchMethodException {
        if (type == FormType.MDI) {
            parentThinlet.populate(bean, mdi);
        } else {
            super.populate(bean, this);
        }
    }

    public void displayBean(Object bean) throws IllegalAccessException,
            InvocationTargetException, NoSuchMethodException {
        if (type == FormType.MDI) {
            parentThinlet.displayBean(bean, mdi);
        } else {
            super.displayBean(bean);
        }
    }

    public Object find(String nome) {
        if (type == FormType.MDI) {
            return parentThinlet.find(mdi, nome);
        } else {
            return super.find(nome);
        }
    }

    public void show(String titulo, int largura, int altura) {
        new FrameLauncher(titulo, this, largura, altura);
    }

    public void addMDI(Object desktop, SireThinlet dialogController,
            String title) {
        setText(dialogController.getMdi(), title);
        this.add(desktop, dialogController.getMdi(), 0);
    }

    public final Dialog getDialog() {
        return dialog;
    }

    public void showDialog() {
        if (type == FormType.DIALOG) {
            packAndShowDialog();
            dialog.setVisible(true);
        }
    }

    private void packAndShowDialog() {
        packDialog();
    }

    private void packDialog() {
        dialog.pack();
        final Rectangle bounds = dialog.getBounds();
        setDialogBounds(bounds.width, bounds.height);
    }

    private void setDialogBounds(int width, int height) {
        final Dimension screen = getToolkit().getScreenSize();
        dialog.setBounds((screen.width - width) / 2,
                (screen.height - height) / 2, width, height);
    }

    private static Dialog createDialog(SireThinlet thinlet) {
        Frame frame = thinlet.getFrame();

        if (frame != null) {
            return new Dialog(frame, true);
        } else if (thinlet instanceof SireThinlet) {
            Dialog dialog = new Dialog(((SireThinlet) thinlet).getDialog());
            dialog.setModal(true);
            return dialog;
        } else {
            return new Dialog(new Frame());
        }
    }

}
